﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using TrenchcoatRobots.Datatypes;
using System.Diagnostics;

namespace TrenchcoatRobots.Classes.ComponentClasses
{
    /// <summary>
    /// Contains a collection of sound effects and methods for interacting with them.
    /// </summary>
    class AudioSource : Component {
        #region Properties
        public List<AudioSample> soundEffects;
        #endregion

        #region Constructors
        /// <summary>
        /// Component for storing and handling one or more sound effects.
        /// </summary>
        /// <param name="gameObjectMethod">The GameObject of which the component will be placed on. Delegate to the ReturnSelf</param>
        public AudioSource (ParentMethod gameObjectMethod)
            : base(gameObjectMethod, "AudioSource", true) {
            soundEffects = new List<AudioSample>();
		}
        /// <summary>
        /// Component for storing and handling one or more sound effects.
        /// </summary>
        /// <param name="gameObjectMethod">The GameObject of which the component will be placed on. Delegate to the ReturnSelf</param>
        /// <param name="sounds">A list of AudioSample that will be added to the AudioSource.</param>
        public AudioSource(ParentMethod gameObjectMethod, List<AudioSample> sounds)
            : base(gameObjectMethod, "AudioSource", true) {
            soundEffects = sounds;
        }
        #endregion

        #region Methods
        /// <summary>
        /// Returns the AudioSample with the specified name, if found.
        /// </summary>
        /// <param name="name">Name of the AudioSample to search for.</param>
        /// <returns>AudioSample with the specified name, if found in list of sound effects.</returns>
        public AudioSample FindSound(string name) {
            for (int i = 0; i < soundEffects.Count; i++)
            {
                if (soundEffects[i].Name.ToLower() == name.ToLower())
                    return soundEffects[i];
            }
            return null;
        }

        /// <summary>
        /// Adds a sound to the sound effect list.
        /// </summary>
        /// <param name="effect">The sound to be added to the sound effect.</param>
        /// <param name="name">The name the sound effect will be given.</param>
        public void AddSound(SoundEffect effect, string name) {
            soundEffects.Add(new AudioSample(effect, name));
        }

        /// <summary>
        /// Adds a sound to the sound effect list.
        /// </summary>
        /// <param name="effect">The AudioSample to add.</param>
        public void AddSound(AudioSample effect) {
            soundEffects.Add(effect);
        }

        /// <summary>
        /// Removes the sound effect at the specified index from the sound effect list.
        /// </summary>
        /// <param name="index">Index of sound to remove (0-based).</param>
        public void RemoveSound(int index) {
            soundEffects.RemoveAt(index);
        }
        /// <summary>
        /// Finds sound with specified name and removes it.
        /// </summary>
        /// <param name="name">Name of sound to remove.</param>
        public void RemoveSound(string name) {
            soundEffects.Remove(FindSound(name));
        }

        #region Play
        /// <summary>
        /// Plays the first sound effect in soundEffects, if not already playing.
        /// </summary>
        public void Play() {
            if (soundEffects.Count > 0)
                soundEffects[0].Play();
        }
        /// <summary>
        /// Plays the sound at the specified position, if not already playing.
        /// </summary>
        /// <param name="index">Index of sound to play.</param>
        public void Play(int index) {
            if (soundEffects.Count > index)
                soundEffects[index].Play();
        }
        /// <summary>
        /// Plays the sound with the specified name, if not already playing.
        /// </summary>
        /// <param name="soundToPlay">Name of sound to play.</param>
        public void Play(string soundToPlay) {
            FindSound(soundToPlay).Play();
        }
        /// <summary>
        /// Plays the first sound effect in soundEffects, if not already playing, with specified pitch and volume.
        /// </summary>
        public void Play(float pitch, float volume)
        {
            if (soundEffects.Count > 0) {
                soundEffects[0].Pitch = pitch;
                soundEffects[0].Volume = volume;
                soundEffects[0].Play();
            }
        }
        /// <summary>
        /// Plays the sound at the specified position, if not already playing, with specified pitch and volume.
        /// </summary>
        /// <param name="index">Index of sound to play.</param>
        public void Play(int index, float pitch, float volume)
        {
            if (soundEffects.Count > index) {
                soundEffects[index].Pitch = pitch;
                soundEffects[index].Volume = volume;
                soundEffects[index].Play();
            }
        }
        /// <summary>
        /// Plays the sound with the specified name, if not already playing, with specified pitch and volume.
        /// </summary>
        /// <param name="soundToPlay">Name of sound to play.</param>
        public void Play(string soundToPlay, float pitch, float volume)
        {
            FindSound(soundToPlay).Pitch = pitch;
            FindSound(soundToPlay).Volume = volume;
            FindSound(soundToPlay).Play();
        }
        #endregion
        #region Pause
        /// <summary>
        /// Pauses the first sound effect in soundEffects, if playing.
        /// </summary>
        public void Pause() {
            if (soundEffects.Count > 0)
                soundEffects[0].Pause();
        }
        /// <summary>
        /// Pauses the sound at the specified position, if playing.
        /// </summary>
        /// <param name="index">Index of sound to pause.</param>
        public void Pause(int index) {
            if (soundEffects.Count > index)
                soundEffects[index].Pause();
        }
        /// <summary>
        /// Pauses the sound with the specified name, if playing.
        /// </summary>
        /// <param name="soundToPlay">Name of sound to pause.</param>
        public void Pause(string soundToPause) {
            FindSound(soundToPause).Pause();
        }
        #endregion
        #region Stop
        /// <summary>
        /// Stops the first sound effect in soundEffects, if playing.
        /// </summary>
        public void Stop() {
            if (soundEffects.Count > 0)
                soundEffects[0].Stop();
        }
        /// <summary>
        /// Stops the sound at the specified position, if playing.
        /// </summary>
        /// <param name="index">Index of sound to stop.</param>
        public void Stop(int index) {
            if (soundEffects.Count > index)
                soundEffects[index].Stop();
        }
        /// <summary>
        /// Stops the sound with the specified name, if playing.
        /// </summary>
        /// <param name="soundToPlay">Name of sound to stop.</param>
        public void Stop(string soundToStop) {
            FindSound(soundToStop).Stop();
        }
        /// <summary>
        /// Stops the first sound effect (after current loop is over) in soundEffects, if playing.
        /// </summary>
        public void StopAfterLoop()
        {
            if (soundEffects.Count > 0)
                soundEffects[0].Stop(false);
        }
        /// <summary>
        /// Stops the sound (after current loop is over) at the specified position, if playing.
        /// </summary>
        /// <param name="index">Index of sound to stop.</param>
        public void StopAfterLoop(int index)
        {
            if (soundEffects.Count > index)
                soundEffects[index].Stop(false);
        }
        /// <summary>
        /// Stops the sound with the specified name (after current loop is over), if playing.
        /// </summary>
        /// <param name="soundToPlay">Name of sound to stop.</param>
        public void StopAfterLoop(string soundToStop)
        {
            FindSound(soundToStop).Stop(false);
        }
        #endregion
        #region Resume
        /// <summary>
        /// Resumes the first sound effect in soundEffects, if paused.
        /// </summary>
        public void Resume() {
            if (soundEffects.Count > 0)
                soundEffects[0].Resume();
        }
        /// <summary>
        /// Resumes the sound at the specified position, if paused.
        /// </summary>
        /// <param name="index">Index of sound to pause.</param>
        public void Resume(int index) {
            if (soundEffects.Count > index)
                soundEffects[index].Resume();
        }
        /// <summary>
        /// Resumes the sound with the specified name, if paused.
        /// </summary>
        /// <param name="soundToPlay">Name of sound to resume.</param>
        public void Resume(string soundToResume) {
            FindSound(soundToResume).Resume();
        }
        #endregion
        #endregion
    }
}
